home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / tfdd.com / KBDEDIT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-07-13  |  7.7 KB  |  244 lines

  1. (******************************************************************************
  2.  
  3.                                 UNIT  KBDEDIT
  4.  
  5.  
  6. -------------------------------------------------------------------------------
  7. Philippe Ranger  (514) 274 4653
  8. First version  26-6-90          Present version  13-7-90
  9. -------------------------------------------------------------------------------
  10. SPECIFICATION
  11.    Defines a lite-line-editor TFDD class, kbdEditC, and installs and opens
  12.       one instance, ke. The text file is ke.t.
  13.    Starting value of string self.s is treated as editable starting input. Reset
  14.       to null on each read.
  15.    One option is to allow user to use Esc key. This will return an empty string
  16.       and set boolean Self.escUsed to true. Otherwise escUsed is false -- it
  17.       will become false again on next read unless Esc is used again.
  18.    Value of boolean echoCR sets whether the Enter that ends any keyboard read
  19.       will be echoed to screen.
  20.    As defined in TP, the CR itself is always recorded (but as ^M^J, as for an
  21.       ordinary text). It remains in buffer until a readln is commanded.
  22.    Convenience method StuffReadln (var srs) simply stuffs the present value
  23.       of string srs (into self.s) before doing an edited readln on it.
  24.    Editor input cannot be redirected.
  25.  
  26. EDITOR SPEC
  27.    Input from s, then kbd, read and echoed from present cursor position, to
  28.       the last column but one in the current window. If window width > 127
  29.       (??), will raise IO error 255.
  30.    User allowed to edit input using ^S, ^D, ^H, ^G and equivalent left arrow,
  31.       right arrow, backspace and Del, plus Home and End.
  32.    Input normally ended with Enter or ^M. S is nulled.
  33.    Self holds boolean toggle fields that can only be changed by clients:
  34.       If echoCR, CR written to screen; else cursor brought to end of input.
  35.       Iff doEsc, user allowed use of Esc, as specified above.
  36.       Iff sdel, default starting input is deleted if first char from user is
  37.          above #31.
  38.    EchoCR is true by default, other toggles false.
  39.  
  40. NOTE
  41.    Underline before a class element name indicates that it is private.
  42.    S and EchoCR are not private. They may be manipulated directly by class
  43.       clients. If this is found embarrassing, field-manipulation methods may
  44.       be added.
  45. ******************************************************************************)
  46.  
  47. UNIT kbdEdit;
  48.  
  49. INTERFACE
  50.  
  51. USES tfdd;
  52.  
  53. CONST
  54.    Mx = 127;                                         (*1 less than buffer size*)
  55.    errorValue = 255;
  56.  
  57. TYPE
  58.    lineS = string[Mx];
  59.  
  60.    kbdEditC = object (tfddC)
  61.       s: lineS;
  62.       escUsed: boolean;
  63.       echoCR, doEsc, sdel: boolean;
  64.       procedure stuffReadln (var srs: lineS);
  65.       function _readLine: integer;
  66.       constructor init
  67.       end;
  68.  
  69. VAR ke: kbdEditC;
  70.  
  71. IMPLEMENTATION
  72. (******************************************************************************
  73. METHODS
  74.  
  75. ******************************************************************************)
  76.  
  77. USES crt, dos;
  78.  
  79. {$F+}
  80.  
  81. PROCEDURE initialize; BEGIN ke.init; END;
  82.  
  83.  
  84. PROCEDURE kbdEditC.stuffReadln (var srs: lineS);
  85. BEGIN
  86.    s := srs;
  87.    readln (t, srs)
  88. END;
  89.  
  90. FUNCTION kbdEditC._readLine: integer;
  91. (*=============================================================================
  92. PRE
  93.    self.echoCR true iff user CR not to be echoed.
  94.    self.s holds starting feed for read.
  95. -------------------------------------------------------------------------------
  96. POST
  97.    See unit specification.
  98.    Self.s is edited input, without CR.
  99.    Returns error value.
  100. -------------------------------------------------------------------------------
  101. METHOD
  102.    All commands, including none, listed in cmdT. Char test starts with normal
  103.       chars, then sets cmd for any command char. Default cmd is none. Last,
  104.       cmd is executed.
  105. =============================================================================*)
  106.  
  107. TYPE cmdT = (none, left, right, del, bs, home, endc, exitc);
  108.  
  109. VAR
  110.    s0: byte absolute s;  (*length(s))*)
  111.    i: byte;              (*cursor position in s*)
  112.    c: char;
  113.    cmd: cmdT;
  114.    Nx: byte;             (*present window width*)
  115.    x, y: byte;           (*whereX, whereY*)
  116.    firstTap: boolean;
  117.  
  118. procedure delAll; begin
  119.    dec (x, i-1); gotoXY (x, y);
  120.    fillchar (s[1], s0, ' ');
  121.    write (s); gotoXY (x, y);
  122.    s0 := 0; i := 1
  123.    end;
  124.  
  125. BEGIN
  126. _readLine := 0;
  127. escUsed := false;
  128. firstTap := true;
  129. Nx := lo(windMax) - lo(windMin) + 1;
  130. if Nx > Mx then begin _readLine := errorValue; EXIT end;
  131. x := whereX; y := whereY;
  132. if x + s0 >= Nx then s0 := Nx - x;
  133. write (s); i := s0+1; x := x + s0;
  134. while true do begin
  135.    c := readkey;
  136.    if firstTap and sdel and (c >= #32) then begin
  137.       firstTap := false;
  138.       delAll
  139.       end;
  140.    cmd := none;
  141.    case c of
  142.       #32..#255: if x < Nx then begin
  143.          inc (s0);
  144.          move (s[i], s[i+1], s0 - i);
  145.          s[i] := c;
  146.          write (copy (s, i, s0+1 - i));
  147.          inc (i);
  148.          inc (x); gotoXY (x, y)
  149.          end;
  150.       #0: case readkey of
  151.          #75: cmd := left;
  152.          #77: cmd := right;
  153.          #83: cmd := del;
  154.          #71: cmd := home;
  155.          #79: cmd := endc
  156.          end;
  157.       ^M: cmd := exitc;
  158.       ^[: if doEsc then begin delAll; escUsed := true; cmd := exitc end;
  159.       ^H: cmd := bs;
  160.       ^G: cmd := del;
  161.       ^S: cmd := left;
  162.       ^D: cmd := right
  163.       end;
  164.    case cmd of
  165.       none: ;
  166.       exitc: begin
  167.          if echoCR then writeln
  168.          else begin inc (x, s0-i); gotoXY (x, y) end;
  169.          EXIT
  170.          end;
  171.       bs: if i > 1 then begin
  172.          delete (s, i-1, 1); dec (i);
  173.          dec (x); gotoXY (x, y);
  174.          write (copy (s, i, s0+1 - i) + ' ');
  175.          gotoXY (x, y)
  176.          end;
  177.       del: if i <= s0 then begin
  178.          delete (s, i, 1);
  179.          gotoXY (x, y);
  180.          write (copy (s, i, s0+1 - i) + ' ');
  181.          gotoXY (x, y)
  182.          end;
  183.       left: if i > 1 then begin dec(i); dec(x); gotoXY(x, y) end;
  184.       right: if i <= s0 then begin inc(i); inc(x); gotoXY(x, y) end;
  185.       home: begin dec (x, i-1); i := 1; gotoXY (x, y) end;
  186.       endc: begin inc (x, s0-i); i := s0; gotoXY (x, y) end
  187.       end
  188.    end
  189. END; (*kbdEditC._readLine*)
  190.  
  191.  
  192. FUNCTION readEdit (var t: textRec): integer;
  193. (*=============================================================================
  194. PRE
  195.    t open for input only;
  196.    t.userData[1..4] holds a pointer to a kbdEditC instance.
  197.    see kbdEditC._readLine.
  198. -------------------------------------------------------------------------------
  199. POST
  200.    User allowed to input with kbdEditO._readLine's editing facilities.
  201.    Result plus ^M^J read to t.
  202. -------------------------------------------------------------------------------
  203. NOTES
  204.    Under TP's read convention, no kbd input is read until Enter (^M) is hit,
  205.       and this is always read also as an eoln, ^M^J. This convention is fol-
  206.       lowed here.
  207.    It is not part of normal text file services that input should be echoed on
  208.       screen. Echoing is the device driver's responsibility. Here it is handled
  209.       within _readLine (which indeed could not work if it could not echo).
  210. =============================================================================*)
  211.  
  212. VAR selfp: ^kbdEditC;
  213.  
  214. BEGIN
  215. with t do begin
  216.    bufEnd := 0;
  217.    bufPos := 0;
  218.    move (userData, selfp, sizeof(selfp));
  219.    with selfp^ do begin
  220.       readEdit := _readLine;
  221.       move (s[1], bufPtr^, length(s));
  222.       bufEnd := length(s);
  223.       s := ''
  224.       end;
  225.    bufPtr^[bufEnd] := ^M; inc (bufEnd);
  226.    bufPtr^[bufEnd] := ^J; inc (bufEnd)
  227.    end
  228. END;  (*readEdit*)
  229.  
  230.  
  231. CONSTRUCTOR kbdEditC.init;
  232. BEGIN
  233.    tfddC.init;
  234.    s := '';
  235.    echoCR := true;
  236.    doEsc := false;
  237.    sdel := false;
  238.    textRec(t).inoutFunc := @readEdit;
  239.    reset (t)
  240. END;
  241.  
  242.  
  243. BEGIN INITIALIZE END.
  244.